/*
 *  Copyright 2008 The MITRE Corporation (http://www.mitre.org/). All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


package org.mitre.lattice.query;

import java.io.IOException;
import java.io.PrintWriter;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.StringTokenizer;

import javax.servlet.ServletException;

import org.mitre.lattice.lattice.LatticeNode;
import org.mitre.mrald.output.HTMLOutput;
import org.mitre.mrald.util.Config;
import org.mitre.mrald.util.FormTags;
import org.mitre.mrald.util.MiscUtils;
import org.mitre.mrald.util.MraldException;
import org.mitre.mrald.util.User;
/**
 *  This HTMLOutput Class specializes the OutputManager class. It specifically
 *  gathers information pertaining to the output columns desired by the user. As
 *  the query is constructed, this class adds output information and updates the
 *  columns and joins necessary to obtain this output information
 *
 *@author     Gail Hamilton
 *@created    January 8, 2004
 *@version    1.0
 */

public class LabellerOutput extends HTMLOutput
{
    private String labelTable = null;
    private String labelColumn = null;
    private String groupName = null;
    /**
     *  Constructor for the HTMLOutput object
     *
     *@since
     */
    public LabellerOutput()
    {
        super();
    }

    /**
     *  This is method that is called from the Workflow. For this step, the
     *  limits are set and the database connection is established. The passed
     *  MsgObject is searched for special DB connection information (looking for
     *  a Datasource name with the value representing the name of the properties
     *  file that houses the connection information). If none is found, the
     *  default is used.
     *
     *@param  msg                                                Description of
     *      Parameter
     *@exception  org.mitre.mrald.control.WorkflowStepException  Description of
     *      Exception
     *@since                                                     1.2
     */
    public void execute( org.mitre.mrald.control.MsgObject msg )
        throws org.mitre.mrald.control.WorkflowStepException
    {
	    //Get the value that contains the column Name, and table Name of the label column.
	    String labelParams = msg.getValue("ParamsLabel")[0];
	    parseLabelParams( labelParams );

	    User user = (User) msg.getReq().getSession().getAttribute(Config.getProperty("cookietag"));
	    if (user == null)
	    {
		    throw new org.mitre.mrald.control.WorkflowStepException("You must login to perform this operation");
	    }

	    if (user.getGroup() == null)
	    {
		    throw new org.mitre.mrald.control.WorkflowStepException("You must login to perform this operation");
	    }
	    groupName = user.getGroup();
	    String[] queries = msg.getQuery();
	    String link =  " AND ";
	    for (int i=0; i< queries.length; i++)
	    {
		    if (queries[i].toUpperCase().indexOf("WHERE") > 0 )
		         link = " AND ";
		    else
			 link = " WHERE ";

		    queries[i] = queries[i] + link + " owner = '" + user.getEmail() + "'";
	    }

	    super.execute(msg);
    }

    public void printNavigation(PrintWriter out)
     {
         out.println( "<center><table cellpadding='0' cellspacing='0' border='0' width='600'>\n" );
         out.println( "<tr><td>\n" );
         out.print( "<script language='JavaScript1.2' type='text/javascript' src='");
         out.print(Config.getProperty("BaseUrl"));
         out.println( "/navi.js'>");
	out.print("</script>\n" );
	 out.print(getJavaScript());

         out.println( "</td></tr>\n" );
         out.println( "</table></center>\n" );
     }
    /**
     *  Retrieve the contents of the result set and send them to out as the guts
     *  of an HTML table. This includes only the header row with the field names
     *  as column titles and the each query result as table rows. The
     *  <table>
     *    , <HTML>, <body>, <title>and <style>tags are not included.
     *
     *@param  out                   the output stream
     *@since                        1.2
     */
    public void printHtmlResults( PrintWriter out )
        throws ServletException, IOException, SQLException
    {

        /*
         * ResultSetMetaData md = rs.getMetaData();
         * int count = md.getColumnCount();
         */

	//String js = getJavaScript();
        //out.println( js );
	out.println( "<tr>" );
	out.println("<form enctype='x-www-form-urlencoded' action='FormSubmit' method='POST' name=\"o\">");
        out.println("<input name='Schema' type='hidden' value='public'><input name='form' type='hidden' value='Labelling'><input value='Set Label' name='workflow' type='hidden'>");
        /*
         * niceNames[] contains the column names, either from the db field name or specified in the HTML form
         */
        StringBuffer headerRow = new StringBuffer( "<tr>" );
        for ( int p = 0; p < niceNames.length; p++ )
        {
            headerRow.append( "<th>" + niceNames[p] + "</th>" );
        }
        headerRow.append( "<th>Set Label</th></tr>" );
        out.println( headerRow.toString() );

	headerRow = new StringBuffer( "<tr>" );
        for ( int p = 0; p < niceNames.length; p++ )
        {
            headerRow.append( "<th></th>" );
        }
        headerRow.append(" <th>All<input type='checkbox' onclick=\"if(this.checked==false){ClearAll('Label');}\n else{CheckAll('Label');}\">");

	headerRow.append( "</th></tr>" );
        out.println( headerRow.toString() );

        /*
         * Iterate through the ResultSet and extract the rows
         * if a custom format exists, use it, otherwise print the column name
         */
        int row_count = 0;
        float fileSize = 0;
        String formattedString;
        while ( ( rs.next() ) &&
                ( ( lineLimitSize == -1 ) || ( row_count < lineLimitSize ) ) &&
                ( ( mbLimitSize == -1 ) || ( fileSize < mbLimitSize ) ) )
        {
            out.print( "<tr>" );
            for ( int i = 0; i < niceNames.length; i++ )
            {
                /*
                 * Custom formatting here
                 */
                if ( classNames[i].equals( "Timestamp" ) )
                {
                    formattedString = getAndFormat( rs.getTimestamp( i + 1 ), formats[i] );
                }
                else if ( classNames[i].equals( "BigDecimal" ) )
                {
                    formattedString = getAndFormat( rs.getBigDecimal( i + 1 ), formats[i] );
                }
                else
                {
                    formattedString = rs.getString( i + 1 );
                }
                out.print( "<td>" + formattedString + "</td>" );
                try
                {
                    fileSize += formattedString.length() + 9;
                    //9 for tags
                }
                catch ( NullPointerException npe )
                {
                    fileSize += 13;
                    //13 for tags and "null"
                }
            }
            // ENDFOR

	    //Add the checkbox with the associated information
	    String labelInfo = "<td><input type=\"checkbox\" checked name=\"Label" + row_count +"\" value=\"Table:" + labelTable + "~Column:" + labelColumn + "~Value:" +  rs.getString(labelColumn) + "~CurrentCOI:" + rs.getString("label") + "\"></td>";


	    out.println( labelInfo);
	    out.println( "</tr>" );
            row_count++;
            fileSize += 10;
            //for row tags
            // for very large result sets, break it up in several tables
            if ( row_count / 1000.0 == ( int ) ( row_count / 1000.0 ) )
            {
                out.println( "</table><table border='1' cellpadding='3'>" + headerRow.toString() );
            }
        }

        out = getGroupList( out);


	/*ResultSet groupRs = stmt.executeQuery("Select latticeGroupName from latticeGroup");
	out.println( "</table><br>Select Label<br><SELECT name='Label'>");
	while ( groupRs.next() )
	{
		String latticeGroup = groupRs.getString("latticeGroupName") ;
		out.println( "<OPTION value='groupName:" + latticeGroup + "'>" + latticeGroup + "</OPTION>");
	}
	out.println( "</SELECT>");*/

        // ENDWHILE
        recordsReturned = row_count;
        bytesReturned = fileSize;
	out.println("<br><br><input value='Set Label' type='submit'><br><br><input value='Reset Form' type='reset'>");
    }

    /**
     * Need to get the values for the Table Name of the label , and the column name
     * e.g. In format "Table:VolumeLabel~Column:VolumeId"
     *
     *@param  out                   the output stream
     *@since                        1.2
     */
    private  PrintWriter getGroupList(PrintWriter out )
        throws ServletException, IOException, SQLException
    {
	    try
	    {
	        GroupList grpList = new GroupList();
	        ArrayList groups = (ArrayList)grpList.getChildren(groupName);
	        out.println( "</table><br>Select Label<br><SELECT name='COI'>");
	        for (int i = 0; i < groups.size(); i++)
	       {
		    String latticeGroup = ((LatticeNode)groups.get(i)).getName();
		    out.println( "<OPTION value=\"" + MiscUtils.checkApostrophe(latticeGroup) + "\">" +  latticeGroup + "</OPTION>");
	        }
	        out.println( "</SELECT>");
	        return out;
	    }
	    catch(MraldException e)
	    {
	    }
	    return null;
    }
    /**
     * Need to get the values for the Table Name of the label , and the column name
     * e.g. In format "Table:VolumeLabel~Column:VolumeId"
     *
     *@param  out                   the output stream
     *@since                        1.2
     */
    private void parseLabelParams( String labelParams )
    {
	    StringTokenizer labelTokens = new StringTokenizer(labelParams, FormTags.TOKENIZER_STR);

	     /*
             *  Parse out the ~ and loop
             */
            while ( labelTokens.hasMoreTokens() )
            {
                String nvp = labelTokens.nextToken();
                /*
                 *  Use the : as a token to get the name value pair.
                 */
                int splitPoint = nvp.indexOf( FormTags.NAMEVALUE_TOKEN_STR );
                if ( splitPoint == -1 )
                {

                }
                else
                {
                    String label = nvp.substring( 0, splitPoint );
		    if (label.equals("Table"))
			    labelTable = nvp.substring( splitPoint + 1 );
		    else
                            labelColumn = nvp.substring( splitPoint + 1 );
                }

            }

    }

    /**
     * Need to get the values for the Table Name of the label , and the column name
     * e.g. In format "Table:VolumeLabel~Column:VolumeId"
     *
     *@param  out                   the output stream
     *@since                        1.2
     */
    private String getJavaScript()
    {
	    String js = "<script type=\"text/javascript\">" +
	     "\n function CheckAll(val) {  \n var ml = document.forms.o;\n var len = ml.elements.length;\n" +
            " for (var i = 0; i < len; i++){ \n  var e = ml.elements[i]; \n e.checked = true; \n if (e.name.indexOf(val)> 0) { e.checked = true;} \n } \n } \n" +
            " function ClearAll(val) { \n var ml = document.forms.o; \n var len = ml.elements.length;\n" +
            " for (var i = 0; i < len; i++){ \n var e = ml.elements[i];\n e.checked = false; if (e.name.indexOf(val) > 0) { e.checked = false;} \n } \n } \n " +
            "</script>";

	    return js;
    }
}

